Skip to content

Conversation

clairep94
Copy link
Collaborator

@clairep94 clairep94 commented Sep 3, 2025

pr05 Typescript Migration 8: Migrate the client/components/Menubar/MenubarSubmenu

Context:

Changes:

  • Menubar/MenubarSubmenu
  • Menubar/contexts

Other:

  • any updates to use named exports

Notes:

I have verified that this pull request:

  • has no linting errors (npm run lint)
  • has no test errors (npm run test)
  • is from a uniquely-named feature branch and is up to date with the develop branch.
  • is descriptively named and links to an issue number, i.e. Fixes #123

@clairep94 clairep94 added the pr05 Grant Projects pr05 Grant Projects label Sep 3, 2025
@clairep94 clairep94 changed the title Pr05/migrate client components final rebuild menubar submenu attempt 2 pr05 Typescript #8: migrate client/components/Menubar/MenubarSubmenu Sep 3, 2025
MENU = MenubarListItemRole.MENU,
LISTBOX = MenubarListItemRole.LISTBOX,
TRUE = 'true'
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khanniie I'm not 100% if this was the correct approach

I was a bit confused because the original file had the below:

MenubarTrigger.propTypes = {
  role: PropTypes.string,
  hasPopup: PropTypes.oneOf(['menu', 'listbox', 'true'])
};

MenubarList.propTypes = {
  children: PropTypes.node,
  role: PropTypes.oneOf(['menu', 'listbox'])
};

I made the assumption the menu bar list item roles and menubar trigger aria-hasPopup are associated in the relationship defined in the enums??
Should we just remove TRUE? I didn't see TRUE being used elsewhere

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the web docs (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-haspopup#description), it looks like they're supposed to be the same!

"Make sure the role of the element that serves as the container for the popup content is a menu, listbox, tree, grid or dialog and that the value of aria-haspopup matches the role of the popup container."

in other words, my understanding is that aria-haspopup is telling the assistive device what kind of container the "trigger button" is about to open, so it should match the type of our submenu containers.

so it should be either menu or listbox, like you said -- i guess true is a valid value (docs say "The value true is the same as menu") but if we're never using it, we should remove

const { isOpen, handlers } = useMenuProps(id);

// `ref` is always a button from MenubarSubmenu, so safe to cast.
const buttonRef = ref as React.RefObject<HTMLButtonElement>;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasn't sure how to resolve this other than casting, but I thought was safe bc this function is only used within this file once and it's always a button ref

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm!! it's kind of surprising to me that typescript wouldn't be able to infer that from the React.forwardRef function params since you gave it the HTMLButtonElement type there but i trust that it doesn't work without casting haha

title,
triggerRole: customTriggerRole,
listRole: customListRole,
triggerRole = 'menuitem',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if string is too loose here, or if there is a specific enum we should be using?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defer to you but we could add another enum for list item roles! since you already have one for the list itself. i think the type would be either menuitem (for the 'menu' containers) or option (for the 'listbox' containers)

@clairep94 clairep94 marked this pull request as ready for review September 3, 2025 18:42
@clairep94
Copy link
Collaborator Author

@raclim @khanniie ready for review! this is build off of PR 7, which was big so might be best to wait till PR 7 is merged to look at this one

khanniie
khanniie previously approved these changes Sep 10, 2025
Copy link
Collaborator

@khanniie khanniie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks so much for putting this together! it was definitely a very complicated file haha but great work

MENU = MenubarListItemRole.MENU,
LISTBOX = MenubarListItemRole.LISTBOX,
TRUE = 'true'
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the web docs (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-haspopup#description), it looks like they're supposed to be the same!

"Make sure the role of the element that serves as the container for the popup content is a menu, listbox, tree, grid or dialog and that the value of aria-haspopup matches the role of the popup container."

in other words, my understanding is that aria-haspopup is telling the assistive device what kind of container the "trigger button" is about to open, so it should match the type of our submenu containers.

so it should be either menu or listbox, like you said -- i guess true is a valid value (docs say "The value true is the same as menu") but if we're never using it, we should remove

const { isOpen, handlers } = useMenuProps(id);

// `ref` is always a button from MenubarSubmenu, so safe to cast.
const buttonRef = ref as React.RefObject<HTMLButtonElement>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm!! it's kind of surprising to me that typescript wouldn't be able to infer that from the React.forwardRef function params since you gave it the HTMLButtonElement type there but i trust that it doesn't work without casting haha


export function useMenuProps(id) {
/** Custom subset of valid list item roles for the Menubar list items */
export enum MenubarListItemRole {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit but it looks like these are values for the container, not the items within the container? should we update the comment and interface name?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe like "MenuContainerRole"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also agree, I think it might make sense to update the name here!

title,
triggerRole: customTriggerRole,
listRole: customListRole,
triggerRole = 'menuitem',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defer to you but we could add another enum for list item roles! since you already have one for the list itself. i think the type would be either menuitem (for the 'menu' containers) or option (for the 'listbox' containers)

@khanniie khanniie requested a review from raclim September 10, 2025 17:20
@raclim
Copy link
Collaborator

raclim commented Sep 11, 2025

Thanks so much for your work on this! I also think this looks great, and I really like how the refactor for the menubarsubmenu component feels more straightforward and easy to read! Can hold on merging if you'd like to make any further tweaks!

@clairep94
Copy link
Collaborator Author

@raclim @khanniie ready for re-review!

Copy link
Collaborator

@khanniie khanniie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one small comment but overall LGTM! thank you so much!

* -----------------------------------------------------------------------------------------------*/

/** Custom subset of valid values for aria-hasPopup for the MenubarTrigger */
enum MenubarTriggerAriaHasPopup {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit of a nit but if it looks exactly the same as menucontainerrole why not just use that instead of duplicating?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr05 Grant Projects pr05 Grant Projects
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants